<template>
  <view class="chat-container">
    <!-- 顶部导航栏 -->
    <view class="nav-bar">
      <view class="nav-back" @click="goBack">
        <text class="iconfont icon-back">‹</text>
      </view>
      <view class="nav-title">智能对话</view>
      <view class="nav-placeholder"></view>
    </view>

    <!-- 聊天消息区域 -->
    <scroll-view 
      class="chat-messages" 
      scroll-y="true" 
      :scroll-top="scrollTop"
      scroll-with-animation="true"
      :scroll-into-view="scrollIntoView"
    >
      <view class="message-list">
        <view 
          v-for="(message, index) in messages" 
          :key="index" 
          :id="'msg-' + index"
          class="message-item"
          :class="message.role === 'user' ? 'user-message' : 'ai-message'"
        >
          <view class="message-content">
            <text>{{ message.content || '' }}</text>
          </view>
          <!-- AI标识图标 -->
          <view v-if="message.role === 'assistant'" class="ai-identifier">
            <text class="ai-icon">🤖</text>
            <text class="ai-label">AI助手</text>
          </view>
          <view class="message-time">
            {{ formatTime(message.timestamp) }}
          </view>
        </view>
        
        <!-- 流式响应内容或加载中提示 -->
        <view v-if="isLoading" class="message-item ai-message" id="loading-msg">
          <view v-if="streamingMessage && streamingMessage.content" class="message-content">
            <text>{{ streamingMessage.content || '' }}</text>
          </view>
          <view v-else class="message-content loading">
            <view class="loading-text">
              <text 
                v-for="(char, index) in thinkingChars" 
                :key="index"
                class="loading-char" 
                :class="thinkingCharClasses[index]"
                :style="{ animationDelay: (index * 0.1) + 's' }"
              >
                {{ char }}
              </text>
            </view>
          </view>
        </view>
        
        <!-- 底部占位元素，用于滚动定位 -->
        <view id="bottom-anchor" style="height: 1px;"></view>
      </view>
    </scroll-view>

    <!-- 输入区域 -->
    <view class="input-area">
      <view class="input-container">
        <input 
          class="message-input"
          v-model="inputMessage"
          placeholder="请输入您的问题..."
          :focus="inputFocus"
          @focus="onInputFocus"
          @blur="onInputBlur"
          @confirm="sendMessage"
          confirm-type="send"
        />
        <button 
          class="send-button"
          :class="{ 'active': inputMessage.trim() }"
          @click="sendMessage"
          :disabled="isLoading || !inputMessage.trim()"
        >
          发送
        </button>
      </view>
    </view>
  </view>
</template>

<script>
import chatAPI from '@/utils/ChatAPI.js'
import { utils, APP_CONFIG, API_PATHS } from '@/utils/config.js'

export default {
  data() {
    return {
      messages: [],
      inputMessage: '',
      inputFocus: false,
      isLoading: false,
      scrollTop: 0,
      scrollIntoView: '',
      memoryId: null,
      thinkingChars: ['a','s','u','r','a','d','a','正','在','思','考','中','.','.','.','.','.'],
      // 流式显示相关状态
      streamingMessage: null,
      // 当前请求任务，用于取消请求
      currentRequestTask: null
    }
  },
  
  computed: {
    thinkingCharClasses() {
      return this.thinkingChars.map((_, index) =>
        index < 7 ? 'char-brand' : (index < 12 ? 'char-text' : 'char-dots')
      )
    }
  },
  
  onLoad() {
    try {
      // 使用用户ID作为memoryId，如果没有则使用默认值
      const userInfo = uni.getStorageSync('asurada_user_info')
      this.memoryId = userInfo?.id || userInfo?.username || 'test_user'
      
      console.log('=== 聊天页面初始化 ===')
      console.log('用户信息:', userInfo)
      console.log('使用的memoryId:', this.memoryId)
      console.log('API配置:', APP_CONFIG.API_BASE_URL)
      
      // 延迟执行，确保组件完全初始化
      setTimeout(() => {
        this.loadChatHistory()
      }, 0)
    } catch (error) {
      console.error('页面初始化错误:', error)
      // 初始化空消息列表，防止渲染错误
      this.messages = []
    }
  },
  
  methods: {
    // 返回上一页
    goBack() {
      uni.navigateBack()
    },
    
    // 加载聊天历史记录
    async loadChatHistory() {
      try {
        console.log('=== 开始加载聊天历史记录 ===')
        console.log('memoryId:', this.memoryId)
        
        // 显示加载提示
        uni.showLoading({
          title: '正在加载聊天记录....',
          mask: true
        })
        
        const response = await chatAPI.getChatHistory(this.memoryId)
        console.log('聊天历史记录响应:', response)
        
        // 隐藏加载提示
        uni.hideLoading()
        
        if (response && response.code === 200 && response.data) {
          // 根据后端返回的ChatMessageDTO格式处理数据，确保数据安全
          this.messages = response.data
            .filter(item => item) // 过滤掉可能为 null 或 undefined 的项
            .map(item => ({
              role: item.sender === 'USER' ? 'user' : 'assistant',
              content: item.content || '',
              timestamp: item.createTime || new Date().getTime()
            }))
          console.log('处理后的消息列表:', this.messages)
          
          // 确保历史记录加载后滚动到底部显示最新消息
          this.$nextTick(() => {
            // 增加延迟时间，确保DOM完全更新，特别是对于长列表
            setTimeout(() => {
              this.scrollToBottom()
            }, 500)
          })
        } else {
          console.log('获取聊天历史记录响应:', response)
          // 无论返回什么，都将消息列表设为空
          this.messages = []
          // 即使没有历史记录，也要滚动到底部，为新对话做准备
          this.$nextTick(() => {
            setTimeout(() => {
              this.scrollToBottom()
            }, 100)
          })
        }
      } catch (error) {
        // 隐藏加载提示
        uni.hideLoading()
        
        if (error.message && error.message.includes('没有聊天记录')) {
          // 没有聊天记录是正常情况，不显示错误提示
          console.log('加载聊天历史失败:', error) // 使用 console.log
          this.messages = []
        } else {
          console.error('加载聊天历史失败:', error) // 其他错误使用 console.error
          uni.showToast({
            title: '加载聊天历史失败',
            icon: 'none'
          })
        }
        
        // 确保在任何情况下都设置空消息列表并滚动到底部
        this.messages = []
        this.$nextTick(() => {
          setTimeout(() => {
            this.scrollToBottom()
          }, 100)
        })
      }
    },
    
    // 发送消息
    async sendMessage() {
      // 如果有正在流式显示的内容，先停止显示
      if (this.streamingMessage) {
        this.stopStreamingDisplay();
      }
      
      if (!this.inputMessage.trim() || this.isLoading) {
        return
      }
      
      const userMessage = this.inputMessage.trim()
      this.inputMessage = ''
      
      console.log('=== 发送消息 ===')
      console.log('用户消息:', userMessage)
      
      // 添加用户消息到界面
      const userMsg = {
        role: 'user',
        content: userMessage,
        timestamp: new Date().getTime()
      }
      this.messages.push(userMsg)
      this.$nextTick(() => {
        // 增加延迟以确保用户消息渲染完成后再滚动
        setTimeout(() => {
          this.scrollToBottom();
        }, 300);
      })
      
      // 设置加载状态
      this.isLoading = true
      
      try {
        // 调用聊天接口，根据后端ChatForm格式
        const chatForm = {
          memoryId: this.memoryId,
          messages: userMessage
        }
        
        console.log('发送的chatForm:', chatForm)
        console.log('API基础URL:', APP_CONFIG.API_BASE_URL)
        
        // 使用新的ChatAPI发送流式消息
        const fullContent = await chatAPI.sendChatMessageStreaming(chatForm, (chunk, accumulatedContent) => {
          // 只有在收到第一个数据块时才创建消息气泡，并隐藏“思考中”提示
          if (this.streamingMessage === null) {
            this.isLoading = false; // 收到第一个块就隐藏思考中
            this.streamingMessage = {
              role: 'assistant',
              content: '',
              timestamp: new Date().getTime()
            };
            this.messages.push(this.streamingMessage);
          }

          // 流式接收数据
          if (chunk !== '[END]') {
            // 使用 splice 来强制更新，确保UI响应
            const index = this.messages.findIndex(msg => msg === this.streamingMessage);
            if (index !== -1) {
              const updatedMessage = { ...this.messages[index], content: accumulatedContent };
              this.messages.splice(index, 1, updatedMessage);
              // 更新引用，以便下次能找到正确的消息对象
              this.streamingMessage = updatedMessage;
            }
            
            // 滚动到底部
            this.$nextTick(() => {
              setTimeout(() => {
                this.scrollToBottom();
              }, 10); // 更短的延迟以获得更流畅的滚动体验
            });
          }
        });
        
        // 确保思考状态在请求结束后关闭
        this.isLoading = false;
        console.log('聊天响应完成:', fullContent)

        // 如果流式回调未触发，则直接创建新消息
        if (this.streamingMessage === null) {
          this.messages.push({
            role: 'assistant',
            content: fullContent,
            timestamp: new Date().getTime()
          });
        } else {
          // 如果流式回调已触发，则更新最终内容
          const index = this.messages.findIndex(msg => msg === this.streamingMessage);
          if (index !== -1) {
            this.messages[index].content = fullContent;
          }
        }
        
        // 清除流式显示状态
        this.streamingMessage = null;
        
        // 确保滚动到底部显示最新消息
        this.$nextTick(() => {
          setTimeout(() => {
            this.scrollToBottom();
          }, 200);
        });
      } catch (error) {
        console.error('发送消息失败:', error)
        uni.showToast({
          title: '发送消息失败，请重试',
          icon: 'none'
        })
        
        // 清除流式显示状态和加载状态
        this.streamingMessage = null;
        this.isLoading = false;
      }
    },
    
    // 输入框获得焦点
    onInputFocus() {
      this.inputFocus = true
      setTimeout(() => {
        this.scrollToBottom()
      }, 300)
    },
    
    // 输入框失去焦点
    onInputBlur() {
      this.inputFocus = false
    },
    
    // 滚动到底部
    scrollToBottom() {
      // 安全检查，确保组件已正确初始化
      if (!this.messages) {
        console.warn('messages 未初始化，跳过滚动')
        return
      }
      
      console.log('=== 执行滚动到底部 ===')
      
      this.$nextTick(() => {
        // 通过先设置为一个接近最大值的值，再设置为最大值，
        // 可以确保每次调用都能触发uni-app scroll-view的滚动更新。
        // 这是解决重复设置相同scrollTop值可能不触发滚动问题的有效技巧。
        const maxScrollTop = 999999
        this.scrollTop = maxScrollTop - 1

        setTimeout(() => {
          this.scrollTop = maxScrollTop
          console.log('强制滚动到底部，scrollTop设置为:', maxScrollTop)
        }, 10) // 使用极短的延迟来确保值的更新被侦听到
      })
    },
    
    // 格式化时间
    formatTime(timestamp) {
      const date = new Date(timestamp || Date.now())
      const now = new Date()
      const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())
      const yesterday = new Date(today)
      yesterday.setDate(yesterday.getDate() - 1)
      
      const messageDate = new Date(date.getFullYear(), date.getMonth(), date.getDate())
      
      // 今天的消息
      if (messageDate.getTime() === today.getTime()) {
        return date.toLocaleTimeString('zh-CN', { 
          hour: '2-digit', 
          minute: '2-digit',
          hour12: false
        }).replace(/^(\d{2}):(\d{2})$/, '$1:$2')
      } 
      // 昨天的消息
      else if (messageDate.getTime() === yesterday.getTime()) {
        return `昨天 ${date.toLocaleTimeString('zh-CN', { 
          hour: '2-digit', 
          minute: '2-digit',
          hour12: false
        }).replace(/^(\d{2}):(\d{2})$/, '$1:$2')}`
      } 
      // 本周内的消息（近7天）
      else if (today.getTime() - messageDate.getTime() < 6 * 24 * 60 * 60 * 1000) {
        const weekdays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
        return `${weekdays[messageDate.getDay()]} ${date.toLocaleTimeString('zh-CN', { 
          hour: '2-digit', 
          minute: '2-digit',
          hour12: false
        }).replace(/^(\d{2}):(\d{2})$/, '$1:$2')}`
      } 
      // 更早的消息
      else {
        return date.toLocaleDateString('zh-CN', { 
          year: 'numeric',
          month: '2-digit', 
          day: '2-digit'
        }).replace(/\//g, '/') + ' ' + date.toLocaleTimeString('zh-CN', { 
          hour: '2-digit', 
          minute: '2-digit',
          hour12: false
        }).replace(/^(\d{2}):(\d{2})$/, '$1:$2')
      }
    },
    
    // 获取字符样式类
    getCharClass(index) {
      if (index < 7) {
        // "asurada" - 蓝色
        return 'char-brand'
      } else if (index < 12) {
        // "正在思考中" - 白色
        return 'char-text'
      } else {
        // "...." - 灰色
        return 'char-dots'
      }
    },

    stopStreamingDisplay() {
      if (this.streamingMessage) {
        // 如果有正在流式显示的消息，直接显示完整内容
        const index = this.messages.findIndex(msg => msg === this.streamingMessage);
        if (index !== -1) {
          this.messages[index] = {
            role: 'assistant',
            content: this.streamingMessage.content || '', // 显示已接收到的内容
            timestamp: this.streamingMessage.timestamp
          };
        }
        
        this.streamingMessage = null;
      }
      
      this.isLoading = false;
      
      // 如果有正在进行的请求，尝试取消它
      if (this.currentRequestTask) {
        this.currentRequestTask.abort();
        this.currentRequestTask = null;
      }
    },
    
    // 在页面卸载时清理资源
    onUnload() {
      // 清理流式显示状态
      if (this.streamingMessage) {
        this.streamingMessage = null;
      }
      
      // 取消正在进行的请求
      if (this.currentRequestTask) {
        this.currentRequestTask.abort();
        this.currentRequestTask = null;
      }
      
      this.isLoading = false;
    }
  }
}
</script>

<style lang="scss" scoped>
.chat-container {
  height: 100vh;
  display: flex;
  flex-direction: column;
  background-color: #1e2433;
}

.nav-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 88rpx;
  padding: 0 30rpx;
  background-color: #2a304d;
  border-bottom: 1rpx solid #3a4366;
  flex-shrink: 0; /* 防止导航栏被压缩 */
}

.nav-back {
  width: 60rpx;
  height: 60rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  
  .iconfont {
    font-size: 36rpx;
    color: #ffffff;
  }
}

.nav-title {
  font-size: 36rpx;
  font-weight: 600;
  color: #ffffff;
}

.nav-placeholder {
  width: 60rpx;
}

.chat-messages {
  flex: 1;
  padding: 20rpx 20rpx;
  overflow-y: auto; /* 允许内容滚动 */
  -webkit-overflow-scrolling: touch; /* 在iOS上提供更流畅的滚动体验 */
}

.message-list {
  display: flex;
  flex-direction: column;
}

.message-item {
  margin-bottom: 30rpx;
  display: flex;
  flex-direction: column;
  
  &.user-message {
    align-items: flex-end;
    
    .message-content {
      background-color: #2a304d;
      color: #ffffff;
      margin-right: 40rpx;
      border-radius: 16rpx;
      padding: 20rpx 30rpx;
      max-width: 70%;
      word-wrap: break-word;
      line-height: 1.4;
      font-size: 30rpx;
      position: relative;
      border: 1rpx solid #3a4366;
      
      /* 用户消息气泡尾部 */
      &::before {
        content: '';
        position: absolute;
        right: -12rpx;
        top: 20rpx;
        width: 0;
        height: 0;
        border: 12rpx solid transparent;
        border-left-color: #2a304d;
        border-right: 0;
      }
    }
  }
  
  &.ai-message {
    align-items: flex-start;
    
    .message-content {
      background-color: #2a304d;
      color: #ffffff;
      margin-left: 20rpx;
      border-radius: 16rpx;
      padding: 20rpx 30rpx;
      max-width: 70%;
      word-wrap: break-word;
      line-height: 1.4;
      font-size: 30rpx;
      position: relative;
      border: 1rpx solid #3a4366;
      
      /* AI消息气泡尾部 */
      &::before {
        content: '';
        position: absolute;
        left: -12rpx;
        top: 20rpx;
        width: 0;
        height: 0;
        border: 12rpx solid transparent;
        border-right-color: #2a304d;
        border-left: 0;
      }
      
      &.loading {
        display: flex;
        align-items: center;
        gap: 10rpx;
      }
    }
  }
}

/* AI标识图标样式 */
.ai-identifier {
  display: flex;
  align-items: center;
  margin-top: 10rpx;
  margin-left: 20rpx;
  
  .ai-icon {
    font-size: 24rpx;
    margin-right: 10rpx;
  }
  
  .ai-label {
    font-size: 24rpx;
    color: #8a8a9a;
  }
}

.message-time {
  font-size: 24rpx;
  color: #8a8a9a;
  margin-top: 10rpx;
  text-align: center;
  padding: 10rpx 0;
}

.loading-text {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
}

.loading-char {
  display: inline-block;
  animation: bounce 2s infinite;
  color: #4e5eff;
  font-weight: bold;
  margin-right: 2rpx;
}

@keyframes bounce {
  0%, 20%, 50%, 80%, 100% {
    transform: translateY(0);
  }
  40% {
    transform: translateY(-10rpx);
  }
  60% {
    transform: translateY(-5rpx);
  }
}

/* 为不同字符添加不同的动画效果 */
.loading-char:nth-child(1),
.loading-char:nth-child(2),
.loading-char:nth-child(3),
.loading-char:nth-child(4),
.loading-char:nth-child(5),
.loading-char:nth-child(6),
.loading-char:nth-child(7) {
  color: #4e5eff;
  font-weight: bold;
}

.loading-char:nth-child(8),
.loading-char:nth-child(9),
.loading-char:nth-child(10),
.loading-char:nth-child(11),
.loading-char:nth-child(12) {
  color: #ffffff;
}

.loading-char:nth-child(n+13) {
  color: #8a8a9a;
  animation-duration: 1s;
}

/* 加载字符颜色类，避免依赖 :nth-child 在不同端的差异 */
.char-brand { color: #4e5eff; font-weight: bold; }
.char-text { color: #ffffff; }
.char-dots { color: #8a8a9a; animation-duration: 1s; }

.input-area {
  background-color: #2a304d;
  border-top: 1rpx solid #3a4366;
  padding: 20rpx 30rpx;
  flex-shrink: 0; /* 防止输入框被压缩 */
}

.input-container {
  display: flex;
  align-items: center;
  gap: 20rpx;
}

.message-input {
  flex: 1;
  height: 80rpx;
  padding: 0 30rpx;
  border: none;
  border-radius: 40rpx;
  font-size: 30rpx;
  background-color: #3a4366;
  color: #ffffff;
  
  &::placeholder {
    color: #8a8a9a;
  }
}

.send-button {
  width: 120rpx;
  height: 80rpx;
  border-radius: 40rpx;
  background-color: #3a4366;
  color: #8a8a9a;
  font-size: 28rpx;
  border: none;
  
  &.active {
    background-color: #07C160;
    color: #ffffff;
  }
  
  &:disabled {
    background-color: #3a4366;
    color: #8a8a9a;
  }
/* 加载字符颜色类，避免依赖 :nth-child 在不同端的差异 */
.char-brand { color: #4e5eff; font-weight: bold; }
.char-text { color: #ffffff; }
.char-dots { color: #8a8a9a; animation-duration: 1s; }

}
</style>
